using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace DebugConsole.Components
{
    /// <summary>
    /// Draw lines in 3D space
    /// </summary>
    public class LineDrawer : DebugComponent
    {
        private Hashtable lineTable = new Hashtable();
        private BasicEffect effect;
        private VertexPositionColor[] vertices;
        private DebugSharedResources resources;

        public const int MaxLineCount = 1000;

        #region Constructor
        public LineDrawer(DebugSharedResources resources)
            : base(resources)
        {
            this.resources = resources;
            this.vertices = new VertexPositionColor[MaxLineCount * 2];
            this.effect = resources.effect;
        }
        #endregion

        #region ShowLine (public methods)
        public void ShowLine(String key, Vector3 v1, Vector3 v2, Color color)
        {
            if (!lineTable.Contains(key))
                this.AddMark(key, v1, v2, color);
            else
                this.SetMark(key, v1, v2, color);

        }

        public void ShowLine(String key, Vector3 v1, Vector3 v2)
        {
            if (!lineTable.Contains(key))
                this.AddMark(key, v1, v2);
            else
                this.SetMark(key, v1, v2);

        }
        #endregion

        #region AddMark/SetMark (private methods)
        private void AddMark(String key, Vector3 v1, Vector3 v2, Color color)
        {
            // Add the line
            lineTable.Add(key, new DebugLine(v1, v2, color));
        }

        private void AddMark(String key, Vector3 v1, Vector3 v2)
        {
            // Add the line
            lineTable.Add(key, new DebugLine(v1, v2));
        }

        private void SetMark(String key, Vector3 v1, Vector3 v2, Color color)
        {
            ((DebugLine)lineTable[key]).v1 = v1;
            ((DebugLine)lineTable[key]).v2 = v2;
            ((DebugLine)lineTable[key]).color = color;
        }

        private void SetMark(String key, Vector3 v1, Vector3 v2)
        {
            ((DebugLine)lineTable[key]).v1 = v1;
            ((DebugLine)lineTable[key]).v2 = v2;
        }
        #endregion

        #region Draw
        public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
        {
            // If there are no lines, don't draw anything.
            if (lineTable.Count == 0) return;

            int i =0;
            foreach (DictionaryEntry m in lineTable)
            {
                vertices[i * 2 + 0].Position = ((DebugLine)m.Value).v1;
                vertices[i * 2 + 1].Position = ((DebugLine)m.Value).v2;
                vertices[i * 2 + 0].Color = ((DebugLine)m.Value).color;
                vertices[i * 2 + 1].Color = ((DebugLine)m.Value).color;
                i++;
                if (i >= MaxLineCount) break;
            }

            // Draw The lines.
            effect.View = resources.gameInfo.ViewMatrix;
            effect.Projection = resources.gameInfo.ProjectionMatrix;
            effect.World = Matrix.Identity;
            effect.VertexColorEnabled = true;
            effect.Begin(SaveStateMode.None);
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                resources.device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, lineTable.Count);
                pass.End();

            }
            effect.End();
        }

        #endregion
    }
}
